import tornado.web
import os
import json
from common.Models import DBSession, Author, VisitorLogs
from utils.LoggerHandler import logger


# 无token信息验证
class BaseHandler(tornado.web.RequestHandler):
    def initialize(self) -> None:
        self.session = DBSession()
        self.logger = logger
        self.page_next = None

    def set_default_headers(self):
        # 后面的*可以换成ip地址，意为允许访问的地址
        self.set_header('Access-Control-Allow-Origin', '*')
        # self.set_header('Content-Type', 'application/json')
        self.set_header('Access-Control-Allow-Headers', 'Authorization, Content-Type,'
                                                        'Access-Control-Max-Age, Access-Control-Allow-Origin')
        self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE')
        self.set_header('Access-Control-Max-Age', 100)

    def options(self):
        print("options is request.")

    def prepare(self):
        self.logger.info("")
        ip = self.request.headers.get("X-Real-IP", self.request.remote_ip)
        self.logger.info(
            "ip:%s, host:%s, uri:%s, method:%s " % (ip, self.request.host, self.request.uri, self.request.method))
        if "upload" not in self.request.uri:
            try:
                self.logger.info("body:%s" % json.loads(self.request.body))
            except:
                self.logger.info("body:%s" % self.request.body)
        self.logger.info("params:%s" % self.get_params())
        # 记录访问记录
        if ("author" not in self.request.uri) or ("manage" not in self.request.uri):
            self.session.add(VisitorLogs(ip_address=ip, host=self.request.host, uri=self.request.uri))
            self.session.commit()

    def write_error(self, status_code: int, **kwargs) -> None:
        if status_code == 404:
            self.render("404.html", title="404")
        elif status_code == 500:
            self.render("500.html", title="500")

    # 请求api返回的数据格式
    @classmethod
    def result(cls, msg="", status=0, data=None):
        res = {"status": status, "msg": msg, "data": data}
        return res

    # 验证错误信息是否包含中文
    # 包含中文的是自定义错误，否则是系统错误
    def check_except_zh(self, e, msg="操作失败！"):
        e_str = e.__str__()
        is_zh = False
        for ch in e_str:
            if u'\u4e00' <= ch <= u'\u9fff':
                is_zh = True
        result = self.result(e_str) if is_zh else self.result(msg)
        return result

    def get_params(self):
        params = dict()
        try:
            for data in self.request.arguments:
                params[data] = self.get_argument(data, None)
            # self.check_sql_inject(params)
            return params
        except:
            self.write(self.result("数据解析失败！"))
            self.finish()

    def get_body(self):
        try:
            data = json.loads(self.request.body)
            # self.check_sql_inject(data)
            return data
        except:
            self.write(self.result("数据解析失败！"))
            self.finish()

    # 自定义返回内容
    def data_except(self, msg):
        raise UserWarning(msg)

    def data_null(self, data, key, msg):
        value = data.get(key, None)
        if value == None:
            self.data_except(msg)
        return value

    @staticmethod
    def get_file_path(year, month, day):
        parent_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "files", year, month, day)
        if not os.path.exists(parent_path):
            os.makedirs(parent_path)
        return parent_path

    # 请求完成后的处理
    def on_finish(self) -> None:
        self.session.close()

    def get_current_user(self):
        try:
            author_id = self.get_secure_cookie("author_id").decode("utf-8")
            author_obj = self.session.query(Author).filter_by(id=int(author_id), is_delete=0).first()
            if not author_obj:
                author_id = None
        except:
            author_id = None
        print(f"author id is {author_id}")
        return author_id


# 有token信息验证
class AuthHandler(BaseHandler):
    def initialize(self) -> None:
        super(AuthHandler, self).initialize()

    def prepare(self):
        super(AuthHandler, self).prepare()
        try:
            token = self.request.headers.get("Authorization", None)
            if not token:
                raise UserWarning("用户身份无效！")

        except Exception as e:
            self.logger.error(e)
            self.write(self.result("用户身份无效，请重新登录！", status=config["token_expire"]))
            self.finish()
